import { NavBar, InfiniteScroll, Popup, Toast } from 'antd-mobile'
import { useNavigate, useParams } from 'react-router-dom'
import classNames from 'classnames'
import styles from './index.module.scss'

import Icon from '@/components/icon'
import CommentItem from './components/CommentItem'
import CommentFooter from './components/CommentFooter'
import { useEffect, useRef, useState } from 'react'
import {
  addCommentApi,
  followApi,
  getCommentsApi,
  getDetailApi,
  unFollowApi,
} from '@/api/detail'
import { ArticleCommentItem, ArticleDetail } from '@/types/data'
import { formatTime } from '@/utils'
import dp from 'dompurify'
import { useHlCode } from '@/hooks'
import Sky from '@/components/Sky'
import NoneComment from '@/components/NoneComment'
import CommentInput from './components/CommentInput'
// 使用枚举类型来指定评论类型：
enum CommentType {
  // 语法：key = val
  Article = 'a', // a 代表对文章的评论
  Comment = 'c', // c 代表对评论的回复
}
console.log('访问枚举类型的值：', CommentType.Article)
const Article = () => {
  const history = useNavigate()
  const { id } = useParams<{ id: string }>()
  // 1. 获取文章详情
  const [detail, setDetail] = useState<ArticleDetail>({} as ArticleDetail)
  useEffect(() => {
    ;(async () => {
      const { data } = await getDetailApi(id!)
      console.log('文章详情：', data)
      setDetail(data)
      // 关闭骨架屏显示
      setLoading(false)
    })()
  }, [])
  // 2. 代码高亮
  useHlCode()

  // 4. 点击滚动到评论列表顶部位置
  const scrollBoxRef = useRef<HTMLDivElement>(null)
  const targetBoxRef = useRef<HTMLDivElement>(null)
  // 记录滚动状态: true 已经滚动到目标位置 | false 没有滚动到目标位置
  const isDone = useRef(false)
  const scrollComment = () => {
    /**
     * 流程：
     * 1. 获取执行滚动的盒子和滚动目标位置的盒子
     * 2. 计算滚动距离 = 目标位置的盒子距离视口高度 - 头部导航高度45 + 内容区域滚动高度 =》getBoundingClientRect
     */
    const scrollBox = scrollBoxRef.current
    const targetBox = targetBoxRef.current
    // 非空判断
    if (!scrollBox || !targetBox) return
    console.log(
      '目标位置的盒子距离视口高度和内容区域滚动高度:',
      targetBox.getBoundingClientRect().top,
      scrollBox.scrollTop
    )
    if (!isDone.current) {
      // 1. 执行滚动到目标位置
      scrollBox.scrollTo({
        // 滚动到距离顶部多远
        top: targetBox.getBoundingClientRect().top - 45 + scrollBox.scrollTop,
        // 添加滚动过渡效果
        behavior: 'smooth',
      })
      isDone.current = true
    } else {
      // 2. 执行滚动到顶部
      scrollBox.scrollTo({
        // 滚动到距离顶部多远
        top: 0,
        // 添加滚动过渡效果
        behavior: 'smooth',
      })
      isDone.current = false
    }
  }

  // 5. 关注文章作者
  const onFollow = async () => {
    /**
     * 反向操作：
     * 1. 如果没有关注过，调用关注接口=》关注
     * 2. 如果已经关注过，调用取关接口=》取关
     */
    try {
      if (detail.is_followed) {
        // 取关
        await unFollowApi(detail.aut_id)
        setDetail({ ...detail, is_followed: false })
      } else {
        // 关注
        await followApi(detail.aut_id)
        setDetail({ ...detail, is_followed: true })
      }
    } catch (error) {}
  }

  // 6. 获取文章的评论列表
  // 评论列表
  const [commentList, setCommentList] = useState<ArticleCommentItem[]>([])
  // 评论列表是否加载完成
  const [hasMore, setHasMore] = useState(true)
  // 存储评论数据的偏移量
  const offsetRef = useRef<string | null>(null)
  async function loadMoreComments() {
    const {
      data: { total_count, last_id, results },
    } = await getCommentsApi(
      CommentType.Article,
      detail.art_id,
      offsetRef.current
    )
    // 追加当前页数据
    setCommentList([...commentList, ...results])
    if (total_count === commentList.length) {
      // 没有数据了，关闭列表的加载
      setHasMore(false)
    } else {
      // 存储下一页数据请求的偏移量
      offsetRef.current = last_id
    }
  }

  // 7. 对文章发表评论
  const [showComment, setShowComment] = useState(false)
  // 打开评论弹层
  const openComment = () => setShowComment(true)
  // 关闭评论弹层
  const closeComment = () => setShowComment(false)
  /**
   * 对文章发表评论
   * @param content 评论内容
   */
  const addComment = async (content: string) => {
    console.log('content:', content)
    /**
     * 1. 调用发表评论后台接口
     * 2. 本地评论列表数据新增一条
     * 3. 更新评论数量
     * 4. 关闭弹层
     */
    try {
      if (!content.trim()) return
      const { data } = await addCommentApi({
        target: detail.art_id, // 文章ID
        content, // 对文章评论内容
      })
      // data.new_obj 新增评论的数据
      // 说明❓：解决默认评论列表数据还没有加载情况下，添加评论重复展现问题
      commentList.length > 0 && setCommentList([data.new_obj, ...commentList])
      setDetail({ ...detail, comm_count: detail.comm_count + 1 })
      closeComment()
      Toast.show({ content: '添加评论成功' })
    } catch (error) {}
  }

  const renderArticle = () => {
    // 文章详情模板分拆
    return (
      detail && (
        <div ref={scrollBoxRef} className="wrapper">
          {/* 1. 文章详情 */}
          <div className="article-wrapper">
            <div className="header">
              <h1 className="title">{detail.title}</h1>

              <div className="info">
                <span>{formatTime(detail.pubdate, 'YYYY年MM月DD日')}</span>
                <span>{detail.read_count} 阅读</span>
                <span>{detail.comm_count} 评论</span>
              </div>

              <div className="author">
                <img src={detail.aut_photo} alt="" />
                <span className="name">{detail.aut_name}</span>
                <span
                  onClick={onFollow}
                  className={classNames(
                    'follow',
                    detail.is_followed ? 'followed' : ''
                  )}
                >
                  {detail.is_followed ? '已关注' : '关注'}
                </span>
              </div>
            </div>
            {/* 文章内容 */}
            <div className="content">
              <div
                className="content-html dg-html"
                dangerouslySetInnerHTML={{
                  __html: dp.sanitize(detail.content),
                }}
              />
              <div className="date">
                发布文章时间：{formatTime(detail.pubdate)}
              </div>
            </div>
          </div>
          {/* 2. 文章评论 */}
          <div className="comment" ref={targetBoxRef}>
            <div className="comment-header">
              <span>全部评论（{detail.comm_count}）</span>
              <span>{detail.like_count} 点赞</span>
            </div>
            {detail.comm_count === 0 ? (
              <NoneComment />
            ) : (
              <div className="comment-list">
                {/* 文章评论列表渲染 */}
                {commentList.map((item) => (
                  <CommentItem key={item.com_id} {...item} />
                ))}
                {/* 无限加载组件 */}
                <InfiniteScroll hasMore={hasMore} loadMore={loadMoreComments} />
              </div>
            )}
          </div>
        </div>
      )
    )
  }

  // 3. 骨架屏：文章详情没有数据的时候，显示骨架屏
  const [loading, setLoading] = useState(true)
  if (loading) {
    return <Sky />
  }

  return (
    <div className={styles.root}>
      <div className="root-wrapper">
        {/* 1. 头部导航 */}
        <NavBar
          onBack={() => history(-1)}
          right={
            <span>
              <Icon type="icongengduo" />
            </span>
          }
        >
          <div className="nav-author">
            <img src={detail.aut_photo} alt="" />
            <span className="name">{detail.aut_name}</span>
            <span
              onClick={onFollow}
              className={classNames(
                'follow',
                detail.is_followed ? 'followed' : ''
              )}
            >
              {detail.is_followed ? '已关注' : '关注'}
            </span>
          </div>
        </NavBar>
        {/* 2. 文章详情和评论 */}
        {renderArticle()}

        {/* 3. 底部评论栏 */}
        <CommentFooter
          openComment={openComment}
          scrollComment={scrollComment}
        />
      </div>
      {/* 对文章评论弹层 */}
      <Popup
        destroyOnClose
        visible={showComment}
        onMaskClick={closeComment}
        position="bottom"
      >
        <CommentInput addComment={addComment} closeComment={closeComment} />
      </Popup>
    </div>
  )
}

export default Article
